package com.hqyj.springboot.modules.account.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hqyj.springboot.modules.account.dao.UserDao;
import com.hqyj.springboot.modules.account.dao.UserDao2;
import com.hqyj.springboot.modules.account.dao.UserRoleDao;
import com.hqyj.springboot.modules.account.dao.UserRoleDao2;
import com.hqyj.springboot.modules.account.entity.UserRole;
import com.hqyj.springboot.modules.common.vo.Result;
import com.hqyj.springboot.modules.account.entity.User;
import com.hqyj.springboot.modules.account.service.UserService;
import com.hqyj.springboot.modules.common.vo.Search;
import com.hqyj.springboot.utils.MD5Util;
import com.hqyj.springboot.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;



import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl implements UserService {

    public final static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);


    @Autowired
    private UserDao userDao;
    @Autowired
    private UserDao2 userDao2;
    @Autowired
    private UserRoleDao userRoleDao;
     @Autowired
    private UserRoleDao2 userRoleDao2;
     @Autowired
     private RedisUtils redisUtils;



    @Override
    public User getUserByUserNameAndPassword(String userName, String Password) {
       return userDao2.getUserByUserNameAndPassword(userName,MD5Util.getMD5(Password));
    }

    @Override
    @Transactional
    public Result<User> login(User user) {
        //获取连续登录错误次数，如果超过三次则返回错误信息，否则继续登录

        String errorLoginKey = String.format("errorLoginCount%s",user.getUserName());
        int count = redisUtils.get(errorLoginKey) == null ? 0 : (Integer)redisUtils.get(errorLoginKey);
        if (count > 3){
            return new Result<>(Result.ResultStatus.FAILD.code, "您已经连续错误登录3次，绑定账户15s");

        }
        //得到subject
        Subject subject = SecurityUtils.getSubject();
        //封装一个登录令牌（装载用户名和密码）
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),
                MD5Util.getMD5(user.getPassword()));


        try {
            //身份认证和资源授权

            subject.login(token);

            subject.checkRoles();
            //获取当前用户并将其设置到session中
            User temp = (User)subject.getPrincipal();
            Session session = subject.getSession();
            session.setAttribute("user",temp);
            //清空错误登录次数
            redisUtils.set(errorLoginKey,0);

            return new Result<User>(Result.ResultStatus.SUCCESS.code, "登录成功!",temp);

        }catch (Exception e){
            e.printStackTrace();
            LOGGER.debug(e.getMessage());
            //将错误登录数加1
            redisUtils.increment(errorLoginKey,1);
            //判断错误登录次数，如果大于3，则设置key过期时间
            count = redisUtils.get(errorLoginKey) == null ? 0 :
                    (Integer)redisUtils.get(errorLoginKey);
            String errorMsg ="";

                    if(count < 3) {
                        errorMsg = String.format("您已连续错误登录 %d 次，还剩 %d 次机会",count,(3 - count));
                    }else {
                        errorMsg = "您已连续错误登录3次，绑定账户15s";
                        redisUtils.expire(errorLoginKey,15);
                    }


            return new Result<User>(Result.ResultStatus.FAILD.code, e.getMessage());
        }


//        User temp = userDao2.getUserByUserNameAndPassword(user.getUserName(), MD5Util.getMD5(user.getPassword()));
//        if (temp == null){
//            return new Result<User>(Result.ResultStatus.FAILD.code, "用户名或密码错误!");
//        }
//        return new Result<User>(Result.ResultStatus.SUCCESS.code, "登录成功!",temp);
    }

    @Override
    public void logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();


    }

    @Override
    @Transactional
    public Result<User> updateUser(User user) {
        List<User> users = Optional.ofNullable(userDao2.getUserByUserName(user.getUserName())).orElse(Collections.emptyList());
        if (users.stream().filter(item -> item.getId() != user.getId()).count() > 0){
            return new Result<User>(Result.ResultStatus.FAILD.code, "用户名已存在!");
        }
        user.setUpdateDate(LocalDateTime.now());

        userDao2.updateUser(user);
        if (user.getRoles() != null && !user.getRoles().isEmpty()){
            userRoleDao2.deleteUserRoleByUserId(user.getId());
            user.getRoles().stream().forEach(item -> {
                UserRole userRole = new UserRole();
                userRole.setCreateDate(LocalDateTime.now());
                userRole.setUpdateDate(LocalDateTime.now());
                userRole.setUserId(user.getId());
                userRole.setRoleId(item.getId());
                userRoleDao2.addUserRole(userRole);
            });
        }
        return new Result<User>(Result.ResultStatus.SUCCESS.code, "用户修改成功!",user);
    }

    @Override
    public User getUserById(int id) {
        return userDao2.getUserAndUserRoleById(id);
    }

    @Override
    public User getUserByUserName(String userName) {
        List<User> users =Optional.ofNullable( userDao2.getUserByUserName(userName)).orElse(Collections.emptyList());

        return users.isEmpty() ? null : users.get(0);


    }

    @Override
    @Transactional
    public Result<Object> deleteUserById(int id) {
        userDao2.deleteUserById(id);
        userRoleDao2.deleteUserRoleByUserId(id);
        return new Result<Object>(Result
                .ResultStatus
                .SUCCESS.code, "用户删除成功!");
    }

    @Override
    public PageInfo<User> getUserBySearch(Search search) {
        search.init();
        PageHelper.startPage(search.getCurrentPage(),search.getPageSize());
        return new PageInfo<User>(Optional
                .ofNullable(userDao2.getUsersBySearchVo(search))
                .orElse(Collections.emptyList()));

    }

    @Override
    public List<User> getUserByKeyword(String keyword) {
        Search search = new Search();
        search.setKeyword(keyword);
        search.init();

        return Optional.ofNullable(userDao2.getUsersBySearchVo(search))
                .orElse(Collections.emptyList());
    }


    @Override
    @Transactional
    public Result<User> addUser(User user) {
      if (StringUtils.isBlank(user.getUserName()) || StringUtils.isBlank(user.getPassword())){
          return new Result<User>(Result.ResultStatus.FAILD.code, "用户名或密码为空!");
      }
        List<User> users = Optional.ofNullable(userDao2.getUserByUserName(user.getUserName()))
                .orElse(Collections.emptyList());
      if (users.size() > 0){
          return new Result<User>(Result.ResultStatus.FAILD.code, "用户名已存在!");
      }
      user.setCreateDate(LocalDateTime.now());
      user.setUpdateDate(LocalDateTime.now());
      user.setPassword(MD5Util.getMD5(user.getPassword()));
      userDao2.addUser(user);
      if (user.getRoles() != null){
          user.getRoles().stream().forEach(item -> {
              UserRole userRole = new UserRole();
              userRole.setCreateDate(LocalDateTime.now());
              userRole.setUpdateDate(LocalDateTime.now());
              userRole.setUserId(user.getId());
              userRole.setRoleId(item.getId());
              userRoleDao2.addUserRole(userRole);
          });
      }
       return new Result<User>(Result.ResultStatus.SUCCESS.code, "用户添加成功!",user);


    }




}
